package com.gitee.form_token.exception;

import com.gitee.form_token.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.nio.file.AccessDeniedException;
import java.util.List;

/**
 * 全局异常处理
 *
 * @author: Saturn
 * @dete: 2024-10-26 21:30
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Result jsonHandle(HttpMessageNotReadableException ex) {
        log.error("自定义 异常：----------------{}", ex.getMessage());
        ex.printStackTrace();
        return Result.fail("Invalid JSON input");
    }

    @ExceptionHandler(RuntimeException.class)
    public Result runtimeHandler(RuntimeException ex) {
        log.error("Runtime 其他异常：----------------{}", ex.getMessage());
        ex.printStackTrace();
        return Result.fail(ex.getMessage());
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public Result assertHandler(IllegalArgumentException ex) {
        log.error("Assert 异常：----------------{}", ex.getMessage());
        ex.printStackTrace();
        return Result.fail(ex.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result entityHandler(MethodArgumentNotValidException ex) {
        log.info("Entity 异常：----------------{}", ex.getMessage());
        String message = "参数异常";
        List<FieldError> errors = ex.getBindingResult().getFieldErrors();
        if (!errors.isEmpty()) {
            message = errors.get(0).getDefaultMessage();
        }
        FieldError fieldError = ex.getBindingResult().getFieldError();
        if (fieldError == null) {
            return Result.fail(message);
        }
        ex.printStackTrace();
        return Result.fail(fieldError.getDefaultMessage());
    }

    @ExceptionHandler(AuthenticationCredentialsNotFoundException.class)
    public Result handleAuthentication(AuthenticationCredentialsNotFoundException ex) {
        log.error("未认证 异常：----------------{}", ex.getMessage());
        return Result.fail("未认证", 500);
    }

    @ExceptionHandler(InsufficientAuthenticationException.class)
    public Result handleInsufficient(InsufficientAuthenticationException ex) {
        log.error("无效认证：----------------{}", ex.getMessage());
        return Result.fail(ex.getMessage());
    }

    @ExceptionHandler(BadCredentialsException.class)
    public Result handleBadCredentials(BadCredentialsException ex) {
        log.error("认证异常：----------------{}", ex.getMessage());
        return Result.fail(ex.getMessage());
    }

    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(value = AuthenticationException.class)
    public Result status401(AuthenticationException ex) {
        return Result.fail(ex.getMessage(), 401);
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = TypeMismatchException.class)
    public Result status400(TypeMismatchException ex) {
        return Result.fail(ex.getMessage(), 400);
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public Result status400(MissingServletRequestParameterException ex) {
        return Result.fail(ex.getMessage(), 400);
    }

    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ExceptionHandler(value = AccessDeniedException.class)
    public Result status403(AccessDeniedException ex) {
        return Result.fail(ex.getMessage(), 403);
    }

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(value = NoHandlerFoundException.class)
    public Result status404(NoHandlerFoundException ex) {
        return Result.fail(ex.getMessage(), 404);
    }

    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public Result status405(HttpRequestMethodNotSupportedException ex) {
        return Result.fail(ex.getMessage(), 405);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(value = Exception.class)
    public Result status500(Exception ex) {
        return Result.fail(ex.getMessage(), 500);
    }
}
